home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’96 / Talking Telnet / source / network / network.c < prev    next >
Text File  |  1996-06-22  |  30KB  |  1,210 lines

  1. /****************************************************************
  2. *    NCSA Telnet for the Macintosh                                *
  3. *                                                                *
  4. *    National Center for Supercomputing Applications                *
  5. *    Software Development Group                                    *
  6. *    152 Computing Applications Building                            *
  7. *    605 E. Springfield Ave.                                        *
  8. *    Champaign, IL  61820                                        *
  9. *                                                                *
  10. *    Copyright (c) 1986-1993,                                    *
  11. *    Board of Trustees of the University of Illinois                *
  12. *****************************************************************
  13. *  Revisions:
  14. *  10/87  Initial source release, Tim Krauskopf
  15. *  2/88  typedef support for other compilers (TK)
  16. *  8/88  Gaige Paulsen - support for MacTCP drivers
  17. *  1/89  TK - conversion to new drivers, minor update for new calling convention
  18. *  6/89  TK - update to MacTCP 1.0 include files and use of GetMyIPAddr()
  19. *  7/92  Scott Bulmahn - add support for 2 global structs, put cursors into an array
  20. *  11/92 Jim Browne - Fixed more bugs than I care to mention.                    
  21. *
  22. */
  23.  
  24. #ifdef MPW
  25. #pragma segment Network
  26. #endif
  27.  
  28. #include "InternalEvents.h"
  29. #include "wind.h"
  30. #include "maclook.proto.h"
  31. #include "menuseg.proto.h"
  32. #include "mainseg.proto.h"
  33. #include "MyMacTCPstructures.h"
  34. #include "network.proto.h"
  35. #include "netevent.proto.h"
  36. #include "tnae.h"
  37. #include "authencrypt.h"
  38. #include "authencrypt.proto.h"
  39.  
  40. #include "errors.proto.h"
  41. #include "telneterrors.h"
  42. #ifdef THINK_C
  43. #pragma options(!profile)
  44. #endif
  45.  
  46. #ifdef __MWERKS__
  47. #pragma profile off
  48. #endif
  49.  
  50. //#define NET_DEBUG_MUCHINFO
  51. //#define    NET_DEBUG
  52. #ifdef    NET_DEBUG
  53. char    net_debug_string[256];
  54. #define    net_debug_print(x)    putln(net_debug_string)
  55. #else
  56. #define    net_debug_print(x)    
  57. #endif
  58.  
  59. //PROTO_UPP(Notify, TCPNotify);
  60. //static    TCPIOCompletionProcPtr        OpenCompleteInit(TCPiopb *pbp);
  61. //PROTO_UPP(OpenCompleteInit, TCPIOCompletion);
  62. //static    TCPIOCompletionProcPtr        CloseCompleteInit(TCPiopb *pbp);
  63. //PROTO_UPP(CloseCompleteInit, TCPIOCompletion);
  64. //static    TCPIOCompletionProcPtr        SendCompleteInit(TCPiopb *pbp);
  65. //PROTO_UPP(SendCompleteInit, TCPIOCompletion);
  66.  
  67. static TCPIOCompletionUPP     OpenCompleteInitUPP = nil;
  68. static TCPIOCompletionUPP     CloseCompleteInitUPP = nil;
  69. static TCPIOCompletionUPP     SendCompleteInitUPP = nil;
  70. static TCPNotifyUPP            NotifyUPP = nil;
  71.  
  72.  
  73. static    void        OpenComplete(MyTCPpbPtr pbp);
  74. static    void        SendComplete(MyTCPpbPtr pbp);
  75. static    void        CloseComplete(MyTCPpbPtr pbp);
  76.  
  77. pascal void Notify(StreamPtr streamPtr, unsigned short code, Ptr uptr, 
  78.                         unsigned short terminReason, struct ICMPReport *icmpMsg);
  79.  
  80. static    wdsEntry    *getSWDS(void);
  81. static    void        returnSWDS(wdsEntry *wds);
  82. static    void        MyPBreturn(MyTCPpbPtr pbp);
  83. static    MyTCPpb        *getPB(short driver,short call, StreamPtr stream, short usernum);
  84. static    void        clearPB(MyTCPpbPtr pbp, short driver, short call, StreamPtr stream);
  85. static    OSErr        xPBControlSync(MyTCPpbPtr pbp);
  86. static    OSErr        xPBControlAsync(MyTCPpbPtr pbp, TCPIOCompletionUPP completionUPP);
  87. static    short        makestream(void);
  88. static    void        reclaim(StreamRPtr p);
  89. static    short        giveback(StreamRPtr p, wdsEntry *wds);
  90. static    void        compressfds(wdsEntry *fds);
  91. static void NetWriteZero(Ptr pointer,long size); //put this here to keep from loading and unlaoding config segment
  92. extern Cursor    *theCursors[];
  93. extern WindRec    *screens;
  94.  
  95. long        MyA5;
  96. short        TCPd = 0;                    /* refnum of TCP drivers */
  97. QHdr        gFreePBQueue;
  98. QHdr        gFreeSWDSQueue;
  99. short         numSWDS=0;                    /* Number of SWDS's ever alloc'd (PM Only) */
  100. StreamRPtr    streams[NPORTS];
  101. ip_port        nnfromport = 0;
  102. Boolean     nextIsUrgent = FALSE;        //CCP 2.7 (See NetUrgent ())
  103.  
  104. void NetWriteZero(Ptr pointer,long size)
  105. {
  106.     while (size--) *pointer++ = 0;
  107. }
  108.  
  109. /**************************************************************************/
  110.  
  111. wdsEntry    *getSWDS(void)
  112. {
  113.     short        n=0;
  114.     wdsEntry *    wds;
  115.     
  116.     if (gFreeSWDSQueue.qHead == NULL)
  117.         wds = (wdsEntry *) myNewPtrCritical( sizeof(wdsEntry) * MAX_SWDS_ELEMS);    
  118.     else
  119.         {
  120.         wds = (wdsEntry *) gFreeSWDSQueue.qHead;
  121.         Dequeue(gFreeSWDSQueue.qHead, &gFreeSWDSQueue);
  122.         }
  123.         
  124.     if (wds == NULL) {    /* sorry, cant allocate WDS (BIG PROBLEM) */
  125.         DoError(508 | NET_ERRORCLASS, LEVEL3, NULL); // <- Is 508 correct?
  126.         forcequit();
  127.         // return ((wdsEntry*) 0L); <- ?? perhaps
  128.         }
  129.  
  130.     return(wds);
  131. }
  132.  
  133. /**************************************************************************/
  134. void    returnSWDS(wdsEntry *wds)
  135. {
  136.     Enqueue((QElemPtr)wds, &gFreeSWDSQueue);
  137. }
  138.  
  139. /**************************************************************************/
  140. void MyPBreturn(MyTCPpbPtr pbp)
  141. {
  142.     Enqueue((QElemPtr)pbp, &gFreePBQueue);
  143. }
  144.  
  145. /**************************************************************************/
  146. MyTCPpb *getPB(short driver,short call, StreamPtr stream, short usernum)
  147. {
  148.     UNUSED_ARG(usernum)
  149.     MyTCPpb *pbp;
  150.  
  151.     if (gFreePBQueue.qHead == NULL)
  152.         pbp = (MyTCPpbPtr) myNewPtrCritical( sizeof(MyTCPpb) );
  153.     else
  154.         {
  155.         pbp = (MyTCPpbPtr) gFreePBQueue.qHead;
  156.         Dequeue(gFreePBQueue.qHead, &gFreePBQueue);
  157.         }
  158.         
  159.     if (pbp == NULL) {    /* sorry, cant allocate TCP buffer (BIG PROBLEM) */
  160.         DoError(508 | NET_ERRORCLASS, LEVEL3, NULL);
  161.         forcequit();
  162.         }
  163.     
  164.     memset((char *) pbp, '\0', sizeof(MyTCPpb));    
  165.     pbp->pb.ioCRefNum = driver;
  166.     pbp->pb.tcpStream = stream;
  167.     pbp->pb.csCode = call;
  168.     
  169.     return(pbp);
  170. }
  171.  
  172. /**************************************************************************/
  173. void clearPB(MyTCPpbPtr pbp, short driver, short call, StreamPtr stream)
  174. {
  175.     NetWriteZero((Ptr)pbp, sizeof(MyTCPpb));    /* BYU LSC - Default to all zeros */    
  176.     pbp->pb.ioCRefNum = driver;
  177.     pbp->pb.tcpStream = stream;
  178.     pbp->pb.csCode = call;
  179. }
  180.  
  181. /**************************************************************************/
  182. OSErr xPBControlSync(MyTCPpbPtr pbp) 
  183.     pbp->pb.ioCompletion = 0L;                         /* Charlie will puke if he ever sees */
  184.     return PBControl((ParmBlkPtr)(pbp),false);         /* his funtions here. -- JMB */
  185. }
  186.  
  187. /**************************************************************************/
  188. OSErr xPBControlAsync(MyTCPpbPtr pbp, TCPIOCompletionUPP completionUPP) 
  189. #ifndef __powerpc__
  190.     pbp->SavedA5 = MyA5;
  191. #endif
  192.     pbp->pb.ioCompletion = completionUPP; 
  193.     return(PBControl((ParmBlkPtr)(pbp),true));        /* async */
  194. }
  195.  
  196. void    SetPortType(short port, short type)
  197. {
  198.     if (port >= 0 && port < NPORTS && (streams[port] != NULL))
  199.         streams[port]->portType = type;
  200. }
  201.  
  202. short    GetPortType(short port)
  203. {
  204.     if (port >= 0 && port < NPORTS && (streams[port] != NULL))
  205.         return(streams[port]->portType);
  206.     else return(-1);
  207. }
  208.  
  209. /**************************************************************************/
  210. /*    Returns an empty stream */ 
  211. short makestream(void)
  212. {
  213.     short        pnum, i;
  214.     StreamRPtr    p;
  215.     MyTCPpbPtr    pbp;
  216.  
  217.     for ( pnum=0; (streams[pnum]!= NULL) && pnum<NPORTS; pnum++)
  218.             ;    /* BYU 2.4.16 */
  219.     
  220.     if (pnum >= NPORTS)
  221.         return(-2);
  222.  
  223.      if (!(p = streams[pnum] = (StreamRPtr) myNewPtrCritical(sizeof(StreamRec))))
  224.          return(-1);
  225.   
  226.      if ((p->buffer = (char *) myNewPtrCritical( TCPBUFSIZ)) == NULL) {
  227.          DisposePtr((Ptr)p);
  228.          streams[pnum] = 0;
  229.           return(-1);
  230.      }
  231.      if ((p->sbuffer = (char *) myNewPtrCritical( TCPBUFSIZ)) == NULL) {
  232.          DisposePtr((Ptr)p->buffer);
  233.          DisposePtr((Ptr)p);
  234.          streams[pnum] = 0;
  235.           return(-1);
  236.      }    
  237.  
  238.     
  239.     for (i=0; i<MAX_FDS_ELEMS; i++) 
  240.         {
  241.         p->fds[ i].length =0; p->fds[ i].ptr = 0L;
  242.         p->exFDS[ i].inuse=0; p->exFDS[ i].fds.length=0;p->exFDS[ i].fds.ptr=0L;
  243.         }
  244.     p->fds[0].length = TCPBUFSIZ;
  245.     p->fds[0].ptr = p->sbuffer;
  246.     p->maxFDSused=0;
  247.     p->aedata = NULL;
  248.     
  249.     pbp=getPB( TCPd, TCPCreate, (long) 0, 7);    /* BYU LSC important - Make create call */
  250.     pbp->pb.csParam.create.rcvBuff = p->buffer;
  251.     pbp->pb.csParam.create.rcvBuffLen = TCPBUFSIZ;
  252.     pbp->pb.csParam.create.notifyProc = NotifyUPP;
  253.  
  254.     if (xPBControlSync(pbp) != noError) 
  255.         DoError (512 | NET_ERRORCLASS, LEVEL2, NULL);
  256.  
  257.     p->stream = pbp->pb.tcpStream;
  258.     
  259.     net_debug_print("Made new stream");
  260.     MyPBreturn(pbp);
  261.     return(pnum);
  262. }
  263.  
  264. /**************************************************************************/
  265. /*    reclaim( p) -
  266.         reclaims buffer space to stream (from pointer p) into the FDS list  */
  267.  
  268. void reclaim(StreamRPtr p)
  269. {
  270.     short n=0, offset=0;
  271.     
  272.     while (offset < MAX_FDS_ELEMS && p->fds[offset].ptr != 0L) offset++;
  273.     
  274.     if (offset >= MAX_FDS_ELEMS) /* offset too large -- cant reclaim */        
  275.         return;
  276.         
  277.     for (n=0 ; n<MAX_FDS_ELEMS && offset< MAX_FDS_ELEMS; n++) 
  278.         {
  279.         if (p->exFDS[ n].inuse) 
  280.             {
  281.             p->fds[ offset++]=p->exFDS[ n].fds;
  282.             p->exFDS[ n].inuse = 0;
  283.             }
  284.         }
  285. }
  286.  
  287. /**************************************************************************
  288.     giveback( p, wds) - gives WDS entries back to the stream by putting them in the 
  289.          mutually exclusive buffer.
  290.     p -> stream
  291.     wds -> wds array            */
  292. short giveback(StreamRPtr p, wdsEntry *wds)
  293. {
  294.     short n=0, m=0;
  295.     
  296.     while ( n< MAX_SWDS_ELEMS && wds[n].ptr !=0L) 
  297.         {
  298.         while (m< MAX_FDS_ELEMS && p->exFDS[ m].inuse) m++;
  299.         if (m >= MAX_FDS_ELEMS)                                    // This was off by one - JMB 2.6
  300.             return(-1);                /* No room in the RECLAIMation center */
  301.         else 
  302.             {
  303.             p->exFDS[ m].inuse =1;
  304.             p->exFDS[ m].fds = wds[n];
  305.             m++;
  306.             }
  307.         n++;
  308.         }
  309.  
  310.     return 0;
  311. }
  312.  
  313. /**************************************************************************/
  314. /*    compressfds( fds)
  315.         compress an fds data structure to make everyone happy */
  316. void compressfds(wdsEntry *fds)
  317. {
  318.     short n,m,compressed;
  319.     
  320.     compressed = 0;
  321.     
  322.     while ( !compressed) {
  323.         compressed=1;
  324.         for (n=0; n< MAX_FDS_ELEMS; n++) 
  325.             {                /* Slow Forwards */
  326.             if (fds[n].ptr) 
  327.                 {                                /* Do if N exists */
  328.                 for ( m = MAX_FDS_ELEMS -1; m>=0; m--) 
  329.                     {    /* Fast Backwards */
  330.                     if (fds[m].ptr && (fds[m].ptr+fds[m].length == fds[n].ptr)) {
  331.                         fds[n].length+=fds[m].length;
  332.                         fds[n].ptr = fds[m].ptr;
  333.                         fds[m].ptr=0L;
  334.                         fds[m].length=0;
  335.                         compressed=0;
  336.                         }
  337. #ifdef CHECKBOTHWAYZ
  338.                     else 
  339.                     if (fds[n].ptr+fds[n].length == fds[m].ptr) 
  340.                         {
  341.                         fds[m].length+=fds[n].length;
  342.                         fds[n].ptr=0L;
  343.                         fds[n].length=0;
  344.                         compressed=0;
  345.                         }
  346. #endif CHECKBOTHWAYZ
  347.                     }
  348.                 }
  349.             }
  350.         }
  351.     m=0;n=0;
  352.     
  353.     /* Close the gaps */
  354.     
  355.     while (n+m < MAX_FDS_ELEMS) 
  356.         {
  357.         while (fds[n+m].ptr ==0L && n+m< MAX_FDS_ELEMS)
  358.             m++;            /* increase gap to valid entry */
  359.         if (n+m<MAX_FDS_ELEMS)
  360.             fds[n]=fds[n+m];
  361.         n++;
  362.         }
  363.     
  364.     /* Get rid of the empty spaces */
  365.     
  366.     n--;        /* for the next loop */
  367.     while (n < MAX_FDS_ELEMS)
  368.         {
  369.         fds[n].ptr=0;
  370.         fds[n++].length=0;
  371.         }
  372. }
  373.  
  374. /***************************************************************************/
  375. /*  Mnetread
  376. *   Read from a connection buffer into a user buffer.  
  377. *   Returns number of bytes read, < 0 on error
  378. * NOTE:
  379. *    current version very inefficient, but hopefully works.
  380. */
  381. short    netread(short pnum, void *buffer, short n)
  382. {
  383.     short        i;
  384.     StreamRPtr    p;
  385.     MyTCPpbPtr    pbp;
  386.     short        inQ, reqdamt;
  387.  
  388.     if (pnum < 0 || pnum >= NPORTS)            /* BYU 2.4.15 */
  389.         return(-2);
  390.  
  391.     if (NULL == (p = streams[pnum]))
  392.         return(-2);
  393.         
  394.     pbp=getPB( TCPd, TCPStatus, p->stream, 1);                /* Make status call */
  395.     if (xPBControlSync(pbp) != noError)                     /* status call bombed */
  396.         DoError (509 | NET_ERRORCLASS, LEVEL1, "Mnetread");
  397.  
  398.     if (pbp->pb.csParam.status.connectionState !=8) {
  399. #ifdef    NET_DEBUG
  400.         sprintf(net_debug_string, "CState: %d is %d",(int)pnum, (int)pbp->pb.csParam.status.connectionState);
  401.         net_debug_print(net_debug_string);
  402. #endif
  403.         MyPBreturn(pbp);
  404.         return(-1);                              /* Connection not established */
  405.         }
  406.     
  407.     inQ = pbp->pb.csParam.status.amtUnreadData;
  408.     reqdamt = n >inQ ? inQ : n;
  409.     
  410.     clearPB( pbp, TCPd, TCPRcv, p->stream);
  411.     pbp->pb.csParam.receive.rcvBuff = buffer;
  412.     pbp->pb.csParam.receive.rcvBuffLen = reqdamt;
  413.     
  414.     if (reqdamt<1) 
  415.         {                                /* Drop out if no data */
  416.         MyPBreturn(pbp);
  417.         return(0);
  418.         }
  419.     
  420.     if ((i = xPBControlSync(pbp)) != noError) {
  421.         DoError (524 | NET_ERRORCLASS, LEVEL1, NULL);
  422.         return(-1);
  423.         }
  424.         
  425.     reqdamt = pbp->pb.csParam.receive.rcvBuffLen;
  426.     if (reqdamt<inQ) 
  427.         netputuev( CONCLASS, CONDATA, pnum,0);            /* more data to get */
  428.  
  429.      /* Decrypt data */
  430.     if (p->aedata && ((tnParams *)p->aedata)->decrypting) {
  431.          unsigned char *cp = (unsigned char *)buffer;
  432.          short len = reqdamt;
  433.          
  434.          while (len-- > 0) {
  435.             *cp = decrypt((tnParams *)p->aedata, (long)(*cp));
  436.             cp++;
  437.         }
  438.     }
  439.  
  440.     MyPBreturn(pbp);
  441.     return(reqdamt);
  442. }
  443.  
  444. //makes the next buffer be sent as urgent data
  445. void netUrgent(void)
  446. {
  447.     nextIsUrgent = TRUE;
  448. }
  449. /************************************************************************/
  450. /* netwrite
  451. *  write something into the output queue, netsleep routine will come
  452. *  around and send the data, etc.
  453. *
  454. */
  455. short    netwrite(short pnum, void *buffer, short nsend)
  456. {    
  457.     StreamRPtr    p;
  458.     wdsEntry    *swds;
  459.     short        remaining, queued, n,m;
  460.     MyTCPpbPtr    pbp;
  461.     OSErr        err;
  462.  
  463. #ifdef    NET_DEBUG_MUCHINFO
  464.     sprintf(net_debug_string, "port: %d\tbuffer: %lx\tnsend %d", pnum,
  465.         (unsigned int)buffer, (int)nsend);
  466.     net_debug_print(net_debug_string);
  467. #endif
  468.  
  469.     if (pnum < 0 || pnum >= NPORTS)        /* BYU 2.4.15 */
  470.         return(-2);
  471.  
  472.     if ( (p = streams[pnum]) == NULL)
  473.         return(-2);
  474.     
  475.     if ( !nsend )
  476.         return(0);
  477.  
  478.     swds = getSWDS();
  479.     
  480.     if (swds == NULL) return(nsend);        // Duh, Mr. Bulmahn. - JMB 2.6
  481.     
  482.     reclaim( p);
  483.  
  484.     compressfds( p->fds);
  485.  
  486.     n=0; remaining = nsend;
  487.  
  488. //    if (p->fds[0].ptr == 0) DebugStr("\pArgh! fds[0] is NULL!");
  489.     
  490.     while (p->fds[n].ptr !=0 && remaining>0 ) {
  491. //        if (n >= MAX_SWDS_ELEMS) DebugStr("\pOverflowing SWDS in while loop!");
  492.         
  493.         swds[n].ptr = p->fds[n].ptr;
  494.         if ( p->fds[n].length > remaining) {
  495.             swds[n].length = remaining;
  496.             p->fds[n].length -= remaining;
  497.             p->fds[n].ptr += remaining;
  498.             remaining=0;
  499.             }
  500.         else 
  501.             {
  502.             swds[n].length =  p->fds[n].length;
  503.             remaining -= p->fds[n].length;
  504.             p->fds[n].length = 0;
  505.             p->fds[n].ptr = 0;
  506.             }
  507.         n++;
  508.         }
  509.  
  510.     if (n>p->maxFDSused) p->maxFDSused=n;
  511.     
  512.     compressfds( p->fds);
  513.  
  514.     queued = nsend-remaining;
  515.     
  516.     for(m=0; m<n; m++) {
  517. #ifdef    NET_DEBUG_MUCHINFO
  518.     sprintf(net_debug_string, "swds[m].ptr: %lx\tswds[m].length: %d", (unsigned int)swds[m].ptr, (int)swds[m].length);
  519.     net_debug_print(net_debug_string);
  520. #endif
  521.         }
  522.         
  523.     for (m=0; m<n; m++) 
  524.         {
  525.         BlockMove(buffer, swds[m].ptr, swds[m].length);    /* BYU LSC - Put data in WDS */
  526.     
  527.         /*
  528.          * encrypt if encrypting the session
  529.          */
  530.         if (p->aedata && ((tnParams *)p->aedata)->encrypting)
  531.             encrypt((tnParams *)p->aedata, (unsigned char *)swds[m].ptr, swds[m].length);
  532.         buffer=(void *)((char *)buffer + swds[m].length);
  533.         }
  534.     
  535.     swds[m].ptr = 0L;
  536.     swds[m].length=0;
  537.     
  538.     pbp=getPB( TCPd, TCPSend, p->stream, 2);            /* Make send call */
  539.     pbp->pb.csParam.send.wdsPtr = (Ptr) swds;
  540.     pbp->pb.csParam.send.pushFlag = p->push;
  541.     pbp->pb.csParam.open.ulpTimeoutValue = (SInt8)gApplicationPrefs->SendTimeout;// timeout value
  542.     pbp->pb.csParam.open.ulpTimeoutAction = 1;                // Abort
  543.     pbp->pb.csParam.open.validityFlags = 0xC0;                // Timeout and action are valid
  544.     if (nextIsUrgent)
  545.     {
  546.         nextIsUrgent = FALSE;
  547.         pbp->pb.csParam.send.urgentFlag = TRUE;
  548.     }
  549.  
  550.     p->push=0;
  551.  
  552.     if ((err = xPBControlAsync(pbp, SendCompleteInitUPP)) != noError) 
  553.         {
  554.         char temp_xvvyz[256];
  555.         
  556.         sprintf(temp_xvvyz, "netwrite: %d", err);
  557.         DoError(510 | NET_ERRORCLASS, LEVEL2, temp_xvvyz);
  558.         return(-1);
  559.         }
  560.  
  561.     return(queued);
  562. }
  563.  
  564. /**************************************************************************/
  565. /*  Mnetpush
  566. *   attempt to push the rest of the data from the queue
  567. *   and then return whether the queue is empty or not (0 = empty)
  568. *   returns the number of bytes in the queue.
  569. */
  570. short netpush(short pnum)
  571. {
  572.     StreamRPtr    p;
  573.     MyTCPpbPtr    pbp;
  574.     short        inQ;
  575.     OSErr        err;
  576.  
  577.     if (pnum < 0 || pnum >= NPORTS)        /* BYU 2.4.15 */
  578.         return(-2);
  579.  
  580.     if (NULL == (p = streams[pnum]))
  581.         return(-2);
  582.  
  583.     pbp=getPB( TCPd, TCPStatus, p->stream, 3);            /* Make status call */
  584. //#ifdef    NET_DEBUG_MUCHINFO
  585. //    sprintf(net_debug_string, "TCPd == %d", TCPd);
  586. //    net_debug_print(net_debug_string);
  587. //#endif
  588.     if ((err = xPBControlSync(pbp)) != noError) {        /* status call bombed */
  589.         char temp_xvvyz[256];
  590.  
  591.         sprintf(temp_xvvyz, "netpush: %d", err);
  592.         DoError(509 | NET_ERRORCLASS, LEVEL2, temp_xvvyz);
  593.         }
  594.         
  595.     inQ = pbp->pb.csParam.status.amtUnackedData;
  596.     MyPBreturn( pbp);
  597.     
  598.     p->push=1;
  599.     return(inQ);
  600. }    
  601.  
  602. /**************************************************************************/
  603. /*  Mnetqlen
  604. *   return the number of bytes waiting to be read from the incoming queue.
  605. */
  606. short netqlen(short pnum)
  607. {
  608.     StreamRPtr    p;
  609.     MyTCPpbPtr    pbp;
  610.     short        inQ;
  611.  
  612.     if (pnum < 0 || pnum >= NPORTS)        /* BYU 2.4.15 */
  613.         return(-2);
  614.  
  615.     if (NULL == (p = streams[pnum]))
  616.         return(-2);
  617.  
  618.     pbp=getPB( TCPd, TCPStatus, p->stream, 4);                /* Make status call */
  619.     if (xPBControlSync(pbp) != noError)                     /* status call failed */
  620.         DoError(509 | NET_ERRORCLASS, LEVEL2, "Mnetqlen");
  621.  
  622.     inQ = pbp->pb.csParam.status.amtUnreadData;
  623.     MyPBreturn( pbp);
  624.     
  625.     p->push = 1;
  626.     return(inQ);
  627. }
  628.  
  629. /**************************************************************************/
  630. /*  Mnetroom()
  631. *    return how much room is available in output buffer for a connection
  632. */
  633. short netroom(short pnum)
  634. {
  635.     StreamRPtr    p;
  636.     short        inQ, n;
  637.  
  638.     if (pnum < 0 || pnum >= NPORTS)        /* BYU 2.4.15 */
  639.         return(-2);
  640.  
  641.     if (NULL == (p = streams[pnum]))
  642.         return(-2);
  643.  
  644.     reclaim( p);
  645.     compressfds( p->fds);
  646.  
  647. #ifdef OLDM
  648.     pbp=getPB( TCPd, TCPStatus, p->stream, 5);            /* Make status call */
  649.     if (xPBControlSync(pbp) != noError) 
  650.         DoError(509 | NET_ERRORCLASS, LEVEL1, "Mnetroom");
  651.  
  652.     inQ = pbp->csParam.status.sendWindow -
  653.                 pbp->csParam.status.amtUnackedData;
  654.     MyPBreturn( pbp);
  655. #else
  656. /*#pragma unused(pbp)    /* BYU LSC */
  657. #endif
  658.  
  659.     inQ = n = 0;
  660.     while (p->fds[n].ptr) {
  661.     
  662.         inQ += p->fds[n].length;                /* add up free list space */
  663.         n++;
  664.         }
  665.  
  666.     return(inQ);
  667. }
  668.  
  669. /**************************************************************************/
  670. void netgetip(unsigned char *st)
  671. {
  672.     struct GetAddrParamBlock mypb;
  673.     /* long netmask; */
  674.  
  675.     net_debug_print("Attempting getmyipaddr");
  676.     
  677.     NetWriteZero((Ptr)&mypb, sizeof(struct GetAddrParamBlock));
  678.     
  679.     mypb.ioCRefNum = TCPd;            /* BYU LSC - TCP driver has to be open by now */
  680.     mypb.csCode = ipctlGetAddr;
  681.  
  682.     if (PBControl((ParmBlkPtr)&mypb, false) != noError) 
  683.         {
  684.         DoError(511 | NET_ERRORCLASS, LEVEL2, NULL);
  685.         return;
  686.         }
  687.     
  688.     BlockMove(&mypb.ourAddress, st, 4);    /* BYU LSC - copy the address */
  689.     /* netmask is here if we want it, too */
  690. }
  691.  
  692. void netfromport            /* next "open" will use this port */
  693.   ( short port)
  694. {
  695.     nnfromport = (ip_port)port;
  696. }
  697.  
  698. /**************************************************************************/
  699. /*  Mnetest?
  700. *  is a particular session established yet?
  701. *  Returns 0 if the connection is in the established state.
  702. */
  703. short netest(short pnum)
  704. {
  705.     StreamRPtr    p;
  706.     MyTCPpbPtr    pbp;
  707.     short        inQ;
  708.  
  709.     if (pnum < 0 || pnum >= NPORTS)        /* BYU 2.4.15 */
  710.         return(-2);
  711.  
  712.     if (NULL == (p = streams[pnum]))
  713.         return(-2);
  714.  
  715.     pbp=getPB( TCPd, TCPStatus, p->stream, 6);            /* Make status call */
  716.     if (xPBControlSync(pbp) != noError)
  717.         {
  718.         DoError(509 | NET_ERRORCLASS, LEVEL2, "Mnetest");
  719.         inQ = -1;
  720.         }
  721.     else 
  722.         inQ = pbp->pb.csParam.status.connectionState !=8;
  723.     MyPBreturn( pbp);
  724.     
  725.     return(inQ);
  726. }
  727.  
  728. /**************************************************************************/
  729. /*  Mnetlisten
  730. *   Listen to a TCP port number and make the connection automatically when
  731. *   the SYN packet comes in.  The TCP layer will notify the higher layers
  732. *   with a CONOPEN event.  Save the port number returned to refer to this
  733. *   connection.
  734. *
  735. *   usage:   portnum = netlisten(service);
  736. *            short service;
  737. *
  738. */
  739.  
  740. short netlisten(ip_port serv)
  741. {
  742.     short        pnum;
  743.     StreamRPtr    p;
  744.     MyTCPpbPtr    pbp;
  745.  
  746.     pnum = makestream();
  747.  
  748.     if (pnum < 0 || pnum >= NPORTS)        /* BYU 2.4.15 */
  749.         return(-2);
  750.  
  751.     if (NULL == (p = streams[pnum]))
  752.         return(-2);
  753.  
  754.     pbp=getPB( TCPd, TCPPassiveOpen, p->stream, 8);            /* Make Listen call */
  755.     
  756.     pbp->pb.csParam.open.localPort = serv;
  757.     
  758.     if (xPBControlAsync(pbp, OpenCompleteInitUPP) != noError) 
  759.         DoError(513 | NET_ERRORCLASS, LEVEL2, NULL);
  760.  
  761.     return(pnum);                        /* BYU 2.4.16 */
  762. }
  763.  
  764. /***********************************************************************/
  765. /*  Mnetgetftp
  766. *  Provides the information that ftp needs to open a stream back to the
  767. *  originator of the command connection.  The other side's IP number
  768. *  and the port numbers to be used to calculate the default data connection
  769. *  number.  Returns values in an integer array for convenient use in 
  770. *  PORT commands.
  771. */
  772. short    netgetftp(short pnum, ip_addr *addr, ip_port *localPort, ip_port *remotePort)
  773. {
  774.     StreamRPtr p;
  775.     MyTCPpbPtr pbp;
  776.     
  777.     if (pnum < 0)
  778.         return(-2);
  779.  
  780.     if (NULL == (p = streams[pnum]))
  781.         return(-2);
  782.  
  783.     pbp=getPB( TCPd, TCPStatus, p->stream, 9);            /* Make status call */
  784.     if (xPBControlSync(pbp) != noError) 
  785.         DoError(514 | NET_ERRORCLASS, LEVEL2, NULL);
  786.  
  787.     *addr = pbp->pb.csParam.status.remoteHost;
  788.     *localPort = pbp->pb.csParam.status.localPort;
  789.     *remotePort = pbp->pb.csParam.status.remotePort;
  790.     MyPBreturn( pbp);
  791.  
  792.     return 0;
  793. }
  794.  
  795. /**************************************************************************/
  796. /*  Open a network socket for the user. */
  797. short netxopen( ip_addr machine, ip_port service,
  798.                 short    timeout    )        // in seconds
  799. {
  800.     short        pnum;
  801.     StreamRPtr    p;
  802.     MyTCPpbPtr    pbp;
  803.  
  804.     pnum = makestream();
  805.  
  806.     if (pnum < 0)
  807.         return(-2);
  808.  
  809.     if (NULL == (p = streams[pnum]))
  810.         return(-2);
  811.  
  812.     pbp=getPB( TCPd, TCPActiveOpen, p->stream, 10);            /* Make Listen call */
  813.     
  814.     pbp->pb.csParam.open.remoteHost = machine;                /* IP # */
  815.     pbp->pb.csParam.open.remotePort = service;                /* Port */
  816.     pbp->pb.csParam.open.localPort = nnfromport;            /* My Port */
  817.     pbp->pb.csParam.open.ulpTimeoutValue = (SInt8)timeout;    // timeout value
  818.     pbp->pb.csParam.open.ulpTimeoutAction = 1;                // Abort
  819.     pbp->pb.csParam.open.validityFlags = 0xC0;                // Timeout and action are valid
  820.     nnfromport=0;                                            /* Next one is random */
  821.     
  822.     if (xPBControlAsync(pbp, OpenCompleteInitUPP) != noError) {
  823.         DoError(515 | NET_ERRORCLASS, LEVEL2, NULL);
  824.         return(-1);
  825.         }
  826.     
  827.     SetPortType(pnum, NO_TYPE);                // Is allocated to the user
  828.     
  829. #ifdef    NET_DEBUG
  830.     sprintf(net_debug_string, "TCPOpen on port #%d", pnum);
  831.     net_debug_print(net_debug_string);
  832. #endif
  833.     return(pnum);                    /* BYU 2.4.16 */
  834. }
  835.  
  836.  
  837. /**************************************************************************/
  838. /* Mnetclose
  839. *  Do appropriate actions to return connection state to SCLOSED which
  840. *  enables the memory for that port to be reused.
  841. *
  842. *    Specifically:
  843. *        o If status is closed, then release the data structures
  844. *        o If status is not close, perform bkgrd close which generates CLOSEDONE,
  845. *            which should make the session layer call us again
  846. */
  847. short netclose(short pnum)
  848. {
  849.     StreamRPtr    p;
  850.     MyTCPpbPtr    pbp;
  851.     OSErr        errorCode;
  852.     short        status;
  853.     static        short count=0;
  854.  
  855.     errorCode = 0;
  856.     
  857.     if (pnum < 0 || pnum >= NPORTS)            /* is a valid port? */
  858.         return(-1);
  859.  
  860.     if ((p = streams[pnum]) == NULL)             /* nothing there */
  861.         return (1);
  862.  
  863.     pbp=getPB( TCPd, TCPStatus, p->stream, 11);            /* Make status call */
  864.     if ((errorCode = xPBControlSync(pbp)) != noError) 
  865.         {
  866.         if ( errorCode == invalidStreamPtr)
  867.         {
  868.             DoError (516 | NET_ERRORCLASS, LEVEL2, "Mnetclose");
  869.             return(-1);
  870.         }
  871.         else
  872.             {
  873.             status=0;
  874.             count =0;
  875.             }
  876.         }
  877.     else 
  878.         {
  879.         status = pbp->pb.csParam.status.connectionState;            /* The connection Status */
  880.         if (count++ ==10) 
  881.             {
  882.             status= 0;
  883.             count =0;
  884.             }
  885.         }
  886.  
  887. #ifdef    NET_DEBUG
  888.     sprintf(net_debug_string, "Mnetclose:error code=%i status=%d",(int)errorCode, status);
  889.     net_debug_print(net_debug_string);
  890. #endif
  891.  
  892.     if (status < 18 && status >2 ) {    /* We aren't closed yet ! */
  893. #ifdef    NET_DEBUG
  894.         sprintf(net_debug_string, "TCPClose being attempted state ...[%d]",status); /* Prolly because outstanding close */
  895.         net_debug_print(net_debug_string);
  896. #endif
  897.         clearPB( pbp, TCPd, TCPClose, p->stream);            /* Make Close call */
  898.         if ((errorCode=xPBControlAsync(pbp, CloseCompleteInitUPP)) != noError) 
  899.             {            /* TCP close failed */
  900.             DoError(517 | NET_ERRORCLASS, LEVEL2, "Mnetclose");
  901.             return (errorCode);
  902.             }
  903.  
  904.         /* Go ahead and return... PB is in use by Async Close call. */
  905.         return (0);                                            /* Return with OK */
  906.         }
  907.  
  908.     /* IF we got here, we must be at closed state, so free memory */
  909.  
  910. #ifdef    NET_DEBUG
  911.     sprintf(net_debug_string, "TCP being released, status = %d", status);
  912.     net_debug_print(net_debug_string);
  913. #endif
  914.  
  915.     clearPB( pbp,TCPd, TCPRelease, p->stream);            /* Make Release call */
  916.     if (xPBControlSync(pbp) != noError) 
  917.         {                /* TCP failed to be released.  Let us know... */
  918.         DoError (518 | NET_ERRORCLASS, LEVEL2, "Mnetclose");
  919.         return (-1);
  920.         }
  921.     
  922.     DisposPtr( p->buffer);                /* Free Receive Buffer */
  923.     DisposPtr( p->sbuffer);                /* Free Send Buffer */
  924.     DisposPtr((Ptr) p);                    /* Free Stream Structure */
  925.     streams[pnum]=0L;
  926.     netportencryptstate(pnum, 0);
  927.  
  928.     MyPBreturn(pbp);
  929.     return(0);
  930. }
  931.  
  932. /**************************************************************************/
  933. /*    Nuke the connection, NOW! */
  934. short    netabort(short pnum)
  935. {
  936.     StreamRPtr    p;
  937.     MyTCPpbPtr    pbp;
  938.     OSErr        errorCode = noErr;
  939.  
  940.     if (pnum < 0 || pnum >= NPORTS)            /* is a valid port? */
  941.         return(-1);
  942.  
  943.     if ((p = streams[pnum]) != NULL)     /* something there */
  944.         {            
  945.         pbp=getPB( TCPd, TCPAbort, p->stream, 12);            /* Make Close call */
  946.         if ((errorCode=xPBControlSync(pbp)) != noError)         /* TCP abort failed.  Bad news */
  947.             DoError (519 | NET_ERRORCLASS, LEVEL1, NULL);
  948.         clearPB( pbp,TCPd, TCPRelease, p->stream);            /* Make Close call */
  949.         if (xPBControlSync(pbp) != noError) 
  950.             {
  951.             DoError (518 | NET_ERRORCLASS, LEVEL2, NULL);
  952.             return(-1);
  953.             }
  954.         }
  955.     else
  956.         return(1);
  957.     
  958.     DisposPtr( p->buffer);                /* Free Receive Buffer */
  959.     DisposPtr( p->sbuffer);                /* Free Send Buffer */
  960.     DisposPtr((Ptr) p);                    /* Free Stream Structure */
  961.     streams[pnum]=0L;
  962.  
  963.     MyPBreturn(pbp);
  964.     return(0);
  965. }
  966.  
  967.  
  968. /**************************************************************************/
  969. /*  Mnetinit
  970. *   Calls all of the various initialization routines that set up queueing
  971. *   variables, static values, reads configuration files, etc.
  972. */
  973.  
  974. void Mnetinit( void)
  975. {
  976.     short    i;
  977.     OSErr    err;
  978.  
  979. #ifndef __powerpc__    
  980.     MyA5 = SetCurrentA5();
  981. #endif
  982.     
  983.     for (i=0; i<NPORTS;i++) {
  984.         streams[i]= (StreamRPtr) 0;
  985.         } 
  986.         
  987.     gFreePBQueue.qHead = NULL;
  988.     gFreePBQueue.qTail = NULL;
  989.     gFreePBQueue.qFlags = 0;
  990.     gFreeSWDSQueue.qHead = NULL;
  991.     gFreeSWDSQueue.qTail = NULL;
  992.     gFreeSWDSQueue.qFlags = 0;
  993.         
  994.     if ((err = OpenDriver("\p.IPP",&TCPd)) != noError)         /* cant open the IP driver */
  995.         {    
  996.         SetCursor(theCursors[normcurs]);
  997.         FatalAlert(CANT_OPEN_MACTCP, 300, err);        // Doesn't return!
  998.         }
  999. }
  1000.  
  1001.  
  1002.  
  1003. /*************************************************************************/
  1004. /*  Mnetshut
  1005. *   Close all the connections and turn off the hardware.
  1006. */
  1007. void netshut(void)
  1008. {
  1009.     short    i;
  1010.  
  1011.     for (i=0; i < NPORTS ; i++) 
  1012.         if (streams[i] != (StreamRPtr) NULL)
  1013.             netabort(i);                        /* Prolly should abort */
  1014. }
  1015.  
  1016. /**************************************************************************/
  1017. short    findbystream(StreamPtr streamPtr)
  1018. {
  1019.     short    pnum=0;
  1020.     
  1021.     while (pnum<NPORTS &&
  1022.             ( (streams[pnum] ==(StreamRPtr)0L) || (streamPtr !=streams[pnum]->stream)))
  1023.         pnum++;
  1024.     if (pnum >=NPORTS)
  1025.         return(-1);
  1026.     else
  1027.         return(pnum);
  1028. }
  1029.  
  1030.  
  1031. /**************************************************************************/
  1032. pascal void Notify(StreamPtr streamPtr, unsigned short code, Ptr uptr, 
  1033.                         unsigned short terminReason, struct ICMPReport *icmpMsg)
  1034. {
  1035.     UNUSED_ARG(uptr)
  1036.     UNUSED_ARG(terminReason)
  1037.     UNUSED_ARG(icmpMsg)
  1038.     StreamRPtr    p;
  1039.     short        pnum;
  1040.     
  1041.     pnum = findbystream(streamPtr);
  1042.     
  1043.     if (pnum < 0 || (p = streams[pnum]) == 0L)
  1044.         return;
  1045.     
  1046.     switch( code) {
  1047.         case TCPTerminate:
  1048.         case TCPClosing:
  1049.             netputevent(CONCLASS, CONCLOSE, pnum,0);
  1050.             break;
  1051.         case TCPULPTimeout:
  1052.             netputevent(CONCLASS, CONFAIL, pnum,0);
  1053.             break;
  1054.         case TCPDataArrival:
  1055.         case TCPUrgent:
  1056.             netputuev(CONCLASS, CONDATA, pnum,0);
  1057.             break;
  1058.         case TCPICMPReceived:
  1059.         default:
  1060.             break;
  1061.         }
  1062.     return;
  1063. }
  1064.  
  1065. /**************************************************************************/
  1066. static void OpenCompleteInit(TCPiopb *pbp)
  1067. {
  1068.     long        saveA5;
  1069.     MyTCPpbPtr    myptr;
  1070.     
  1071.     myptr = (MyTCPpbPtr)pbp;
  1072.  
  1073. #ifndef _powerpc_
  1074.     saveA5 = SetA5(myptr->SavedA5);
  1075. #endif
  1076.  
  1077.     OpenComplete(myptr);
  1078.  
  1079. #ifndef _powerpc_
  1080.     SetA5(saveA5);
  1081. #endif
  1082. }
  1083.  
  1084. /**************************************************************************/
  1085. void    OpenComplete(MyTCPpbPtr pbp)
  1086. {
  1087.     StreamRPtr    p;
  1088.     short        pnum;
  1089.  
  1090.     pnum= findbystream(pbp->pb.tcpStream);
  1091.     
  1092.     if (pnum < 0 || (p = streams[pnum]) == 0L) { 
  1093.         MyPBreturn(pbp); //BUGG:  Shouldn't we return here so we don't MyPBreturn twice? 
  1094.         return;             //I'll assume so (CCP)
  1095.     }
  1096.     if (pbp->pb.ioResult !=noError) 
  1097.         netputevent(CONCLASS, CONFAIL, pnum,pbp->pb.ioResult);    /* Failure ... */
  1098.     else 
  1099.         netputevent(CONCLASS, CONOPEN, pnum,0);            /* Success ! */
  1100.     
  1101.     MyPBreturn( pbp);
  1102. }
  1103.  
  1104. /**************************************************************************/
  1105. void    SendComplete(MyTCPpbPtr pbp)
  1106. {
  1107.     StreamRPtr    p;
  1108.     short        pnum;
  1109.     wdsEntry    *swds;
  1110.  
  1111.     swds = (wdsEntry *) pbp->pb.csParam.send.wdsPtr;
  1112.     
  1113.     pnum = findbystream(pbp->pb.tcpStream);
  1114.     
  1115.     if (pnum < 0 || (p = streams[pnum]) == 0L) {
  1116.         MyPBreturn(pbp);
  1117.         return;
  1118.         }
  1119.         
  1120.     MyPBreturn( pbp);
  1121.     giveback( p, (wdsEntry *) pbp->pb.csParam.send.wdsPtr);    /* BYU LSC - Give this back.... NOW */
  1122.     returnSWDS( swds);
  1123. }
  1124.  
  1125.  
  1126. /**************************************************************************/
  1127. static void SendCompleteInit(TCPiopb *pbp)
  1128. {
  1129.     long        saveA5;
  1130.     MyTCPpbPtr    myptr;
  1131.     
  1132.     myptr = (MyTCPpbPtr)pbp;
  1133.  
  1134. #ifndef _powerpc_
  1135.     saveA5 = SetA5(myptr->SavedA5);
  1136. #endif
  1137.     
  1138.     SendComplete(myptr);
  1139.     
  1140. #ifndef _powerpc_
  1141.     SetA5(saveA5);
  1142. #endif
  1143. }
  1144.  
  1145. /**************************************************************************/
  1146. void    CloseComplete(MyTCPpbPtr pbp)
  1147. {
  1148.     StreamRPtr    p;
  1149.     short        pnum;
  1150.  
  1151.     pnum= findbystream(pbp->pb.tcpStream);
  1152.     
  1153.     if (pnum < 0 || (p = streams[pnum]) == 0L)
  1154.       {
  1155.         netputevent(SCLASS, CLOSEDONE+1, pnum,0);
  1156.         MyPBreturn(pbp);
  1157.         return;
  1158.       }
  1159.         
  1160.     if (pbp->pb.ioResult !=noError) 
  1161.         netputevent(SCLASS, CLOSEDONE+1, pnum,0);
  1162.     else 
  1163.         netputevent(SCLASS, CLOSEDONE, pnum,0);            /* Success ! */
  1164.  
  1165.     MyPBreturn( pbp);
  1166. }
  1167.  
  1168. /**************************************************************************/
  1169. static void CloseCompleteInit(TCPiopb *pbp)
  1170. {
  1171.     long        saveA5;
  1172.     MyTCPpbPtr    myptr;
  1173.     
  1174.     myptr = (MyTCPpbPtr)pbp;
  1175.  
  1176. #ifndef _powerpc_
  1177.     saveA5 = SetA5(myptr->SavedA5);
  1178. #endif
  1179.     
  1180.     CloseComplete(myptr);
  1181.     
  1182. #ifndef _powerpc_
  1183.     SetA5(saveA5);
  1184. #endif
  1185. }
  1186.  
  1187. short netportencryptstate (short port, Ptr edata)
  1188. {
  1189.     StreamRPtr    p;
  1190.  
  1191.     if (port < 0 || port >= NPORTS)
  1192.          return(-2);
  1193.  
  1194.      if ((p = streams[port]) == NULL)
  1195.          return(-2);
  1196.  
  1197.     p->aedata = edata;
  1198.  
  1199.      return 0;
  1200. }
  1201. void networkUPPinit(void)
  1202. {
  1203.     OpenCompleteInitUPP  =     NewTCPIOCompletionProc(OpenCompleteInit);
  1204.     CloseCompleteInitUPP =     NewTCPIOCompletionProc(CloseCompleteInit);
  1205.     SendCompleteInitUPP  =     NewTCPIOCompletionProc(SendCompleteInit);
  1206.     NotifyUPP             =  NewTCPNotifyProc(Notify);
  1207. }
  1208.